package com.example.framework.baseController;

import com.example.framework.baseService.TokenService;
import com.example.project.constant.Constant;
import com.example.project.entity.UserInfoBean;
import com.example.project.service.UserService;
import com.example.utils.md5.MD5Util;
import com.example.utils.redis.RedisUtils;
import io.swagger.annotations.Api;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**
 * @UserLoginToken 在数据访问接口中加入登录操作注解
 */
@RestController
@Api("登录接口")
@RequestMapping("/LoginShiroController")
public class LoginShiroController {

    @Autowired
    UserService userService;


    @Autowired
    TokenService tokenService;

    @Autowired
    public RedisUtils redisCache;


    //验证shiro框架
    @PostMapping("/loginSafe")
    public String login(@RequestParam("userName") String userName,
                        @RequestParam("password") String password,HttpServletResponse response,
                        Model model) {
        //根据用户名获取用户信息
        UserInfoBean userForBase = userService.selectUserByUsername(userName);
        //获取当前登录用户
        Subject subject = SecurityUtils.getSubject();
        //将接收密码与该用户在数据库中的密码校验
        //MD5Util.verify(password, userForBase.getPassword())?userForBase.getPassword():password
        //将加密的赋值给接收，解决UsernamePasswordToken 无法将密码与加密的密码校验的问题
        //封装用户登录的数据，以便校验
        UsernamePasswordToken subjectInfo = new UsernamePasswordToken(userName,MD5Util.verify(password, userForBase.getPassword())?userForBase.getPassword():password);
        try {//成功
            subject.login(subjectInfo);//subject对象匹配登录密码
            // 登录成功 将 Token 写入到 Response 的 Header，方便前端刷新 Token 从 Header 取值
            String token = tokenService.getToken(userForBase);
            HttpServletResponse httpServletResponse = (HttpServletResponse) response;
            httpServletResponse.setStatus(HttpServletResponse.SC_OK);
            httpServletResponse.addHeader(Constant.AUTHORIZATION_HEADER, token);

            userForBase.setToken(token);
            userForBase.setLoginTime(new Date());

            redisCache.set("bearer "+token, userForBase);
            redisCache.expire(token, 60*10);

            return "index";
        } catch (UnknownAccountException e) {//用户名不存在
            model.addAttribute("msg", "用户名不存在");
            return "login";
        } catch (IncorrectCredentialsException e) {//密码错误
            model.addAttribute("msg", "密码错误");
            return "login";
        }
    }
}
